package com.tank.game.launch;

import com.tank.game.api.LaunchPanel;
import com.tank.game.api.Position;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

/**
 * @author Zed
 */
public class GamePanel extends JFrame implements LaunchPanel {

    /**
     * 游戏画板类
     */
    private Dimension dimension;

    private Map<ShowObject<? extends Shape>, JPanel> showObjectJPanelMap;

    public GamePanel() {
        this.showObjectJPanelMap = new ConcurrentHashMap<>();
        initFrame();
        initWidthAndHeight();
    }

    private void initFrame() {
        //居中
        this.setLocationRelativeTo(null);
        //可拉伸
        this.setResizable(true);
        //可见
        this.setVisible(true);
        //设置关闭
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void initWidthAndHeight() {
        Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();//获得屏幕尺寸
        int width = (int) (dimension.width * 0.5);
        int height = (int) (dimension.height * 0.5);
        //窗口的坐标和尺寸，这种方式居中
        this.setBounds((dimension.width - dimension.width / 2) / 2, (dimension.height - dimension.height / 2) / 2, width, (int) (dimension.height * 0.5));
        this.dimension = new Dimension(width, height);
    }

    @Override
    public Dimension getDimension() {
        return this.dimension;
    }

    @Override
    public BufferedImage getCurrentBufferedImage() {
        return null;
    }

    @Override
    public void draw(ShowObject showObject) {
        this.innerDraw(showObject, null);
    }

    private void innerDraw(ShowObject showObject, Consumer<Graphics> consumer) {
        // 如果存在已初始化
        JPanel jpanel = this.showObjectJPanelMap.computeIfPresent(showObject, (key, value) -> {
            Position position = showObject.getPosition();
            position.getDegree();
            value.repaint(position.getX(), position.getY(), showObject.getWidth(), showObject.getHeight());
            this.repaint();
            return value;
        });

        if (jpanel == null) {
            ShowObjectAdapter showObjectAdapter = new ShowObjectAdapter(showObject, consumer);
            this.showObjectJPanelMap.put(showObject, showObjectAdapter);
            this.add(showObjectAdapter);
        }

    }

    @Override
    public void draw(ShowObject showObject, Consumer<Graphics> consumer) {
        this.innerDraw(showObject, consumer);
    }

    private class JPanelAdapter extends JPanel {

        private Consumer<Graphics> consumer;

        JPanelAdapter(Consumer<Graphics> consumerGraphics) {
            this.consumer = Objects.requireNonNull(consumerGraphics, "\"consumerGraphics\" cannot be null.");
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            consumer.accept(g);
        }
    }

    private class ShowObjectAdapter extends JPanel {

        private ShowObject showObject;

        private Consumer<Graphics> consumer;

        private boolean init = true;

        ShowObjectAdapter(ShowObject showObject) {
            this.showObject = Objects.requireNonNull(showObject, "\"showObject\" cannot be null.");
        }

        ShowObjectAdapter(ShowObject showObject, Consumer<Graphics> consumer) {
            this.showObject = Objects.requireNonNull(showObject, "\"showObject\" cannot be null.");
            this.consumer = consumer;
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);

            Shape shape = (Shape) this.showObject.getObject();
            if (shape == null && consumer == null) {
                throw new RuntimeException("shape and graphics Cannot be both empty");
            }
            if (shape == null) {
                if (consumer != null && init) {
                    consumer.accept(g);
                }
            } else {
                //TODO
            }
        }
    }
}